/**
 * widget-core.js: Code that is common to all widgets and executed by all widgets.
 * 
 * This file sets up the widget side of the API wormhole and binds the postMessage
 * handler.
 */
(function() {
	//whether or not this widget is initialized.
	var initialized = false;
	
	//Local environment. Populated in the wormhole callback.
	window.LocalEnvironment = {
		trustedModuleQueue: {},
		userID: null,
		apiKey: null
	};
	
	//Widgets are "started" via wormhole callback.
	//Widget execution begins after environment initialization.
	$.wormhole.ready(function(env) {
		if (!initialized) {
			//Create Environment object and set initialized flag.
			initialized = true;
			window.Environment = env;
			
			function finish() {
				//This is the final magic which allows us to call the API functions
				//in widgets. The "around" advice replaces the method calls and makes
				//an async call back to the parent window!
				$.wormhole({ ns: 'Core', target: Core });
				$.wormhole({ ns: 'Thread', target: Thread });
				$.wormhole({ ns: 'Page', target: Page });
				$.wormhole({ ns: '__wwBridge', target: __wwBridge });
				$.wormhole({ ns: '__wwBridge.Cloud', target: __wwBridge.Cloud });
				$.wormhole({ ns: '__wwBridge.UI', target: __wwBridge.UI });
							
				//Execute this widget.
				Widget._readyCallback();
			}
				
			//Wait for local environment.
			function waitForLocalEnvironment(times) {
				return function() {
					//start at 0.
					if (times == 9) {
						alert('Waited 10 times for local environment. Giving up');
						return;
					}
					else {
						var userID = $.jStorage.get('userID');
						var apiKey = $.jStorage.get('apiKey');
						if (!userID || !apiKey) {
							setTimeout(waitForLocalEnvironment(times + 1), 2000);
						}
						else {
							window.LocalEnvironment.userID = userID;
							window.LocalEnvironment.apiKey = apiKey;
							finish();
						}
					}
				}
			}
			
			if (!Environment.CORE) {
				waitForLocalEnvironment(0)();
			}
			else {
				finish();
			}
		}
	});
	
	//Initialization handshake listener.
	$.pm.bind('handshake', function(handshake) {
		if (handshake.state == 'needUUID') {
			var uuid = $.uuid();
			window.LocalEnvironment.uuid = uuid;
			
			$.pm({
				target: window.parent,
				type: 'handshake',
				data: { state: 'uuid', uuid: uuid },
				error: function() { alert('Trust Handshake failed from widget end (State = uuid)'); }
			});
		}
		if (handshake.state == 'gotUUID') {
			//No longer accept anymore handshake requests.
		}
	});
	
	//Trusted module handshake listener.
	$.pm.bind('tfxTrustedModuleHandshake', function(handshake) {
		var module = LocalEnvironment.trustedModuleQueue[handshake.moduleName];
		if (!module) {
			alert('Trusted Module Handshake failed from widget end');
			return;
		}

		if (handshake.state == 'verified') {
			Cloud.getPreference(module.name, function(pref) {
				if (pref.value != 'alwaysRun') {
					var permission = Widget.requestTrustedModulePermission(module);
				}
				else {
					var permission = true;
				}
				
				if (permission === true) {
					$.pm({
						target: window.parent,
						type: 'tfxTrustedModuleHandshake',
						data: { 
							state: 'run',
							uuid: LocalEnvironment.uuid,
							moduleName: module.name,
							moduleScript: module.script
						}
					});
				}
			});
		}
	});
	
	//Listen for messages to this widget.
	$.pm.bind('message', function(payload) {
		var handler = Widget.getMessageHandler(payload.message);
		if (handler) {
			handler(payload.data);
		}
	});

})();